﻿#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="TableLayoutPanel.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2011 
//       Roland Rosenkranz (Glatzemann@email.de)
// </copyright>
// <license>
//   This file is part of starLiGHT.GUI.
//
//   It is released under the Microsoft Public License (Ms-PL).
//
//   You should have received a copy of the Microsoft Public License
//   along with starLiGHT.GUI. If not, see http://sle.codeplex.com/license.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.GUI are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev:: 9631                  $:  Revision of last commit *
// * $Author:: unknown            $:  Author of last commit   *
// * $Date:: 2011-05-03 11:00:42 #$:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

namespace starLiGHT.GUI.Widgets
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Xna.Framework;
    #endregion

    public class TableLayoutPanel : ContainerWidget
    {
        #region Private Members
        private float[] columnsWidth;
        private float[] rowsHeight;
        private Cell[,] cells;
        #endregion

        #region Constructors
        public TableLayoutPanel(GuiManager manager, string name, int columnCount, int rowCount, float[] columnSizePattern, float[] rowSizwPattern)
            : base(manager, name)
        {
            float[] sizes = new float[columnCount + rowCount];

            for (int i = 0; i < columnCount; i++)
            {
                sizes[i] = columnSizePattern[i % columnSizePattern.Length];
            }

            for (int j = 0; j < rowCount; j++)
            {
                int k = columnCount + j;
                sizes[k] = rowSizwPattern[j % rowSizwPattern.Length];
            }

            this.Initialize(columnCount, sizes);
        }

        /// <summary>
        /// Initializes a new instance of the TableLayoutPanel class.
        /// </summary>
        /// <param name="manager">The reference to the gui manager</param>
        /// <param name="name">The name of this widget.</param>
        /// <param name="columnCount">the count of columns</param>
        /// <param name="columnsAndRowsLength">
        /// until columnCount, it defines the width of the columns. 
        /// all further numbers define the height of the rows (and the count of rows)
        /// </param>
        /// <remarks>To don't get confused, call the constructor like this:
        /// TableLayoutPanel table = new TableLayoutPanel(guiManager, name,
        ///     3,              // column count
        ///     90f, 5f, 90f,   // the width's of the three columns
        ///     20f,          // the height of the first row
        ///     5f,           // the height of the second row
        ///     20f,          // the height of the third row
        ///     30f           // the height of the fourth row
        ///     );
        /// </remarks>
        public TableLayoutPanel(GuiManager manager, string name, int columnCount, params float[] columnsAndRowsLength)
            : base(manager, name)
        {
            this.Initialize(columnCount, columnsAndRowsLength);
        }
        #endregion

        public int RowCount
        {
            get
            {
                return this.rowsHeight.Length;
            }
        }

        public int ColumnCount
        {
            get
            {
                return this.columnsWidth.Length;
            }
        }

        public Widget this[int column, int row]
        {
            get
            {
                if (!this.BoundCheck(column, row))
                {
                    throw new ArgumentException("out of tables bounds");
                }

                return this.cells[column, row].Content;
            }

            set
            {
                if (!this.BoundCheck(column, row))
                {
                    throw new ArgumentException("out of tables bounds");
                }

                if (this.cells[column, row].Content != null)
                {
                    Widgets.Remove(this.cells[column, row].Content);
                }

                // TODO: define inside the cell struct, how the widget is located and resized
                value.Location = this.GetLocalCellPosition(column, row);
                value.Size = new Vector2(this.columnsWidth[column], this.rowsHeight[row]);

                this.cells[column, row].Content = value;
                Widgets.Add(value);
            }
        }

        public Vector2 GetLocalCellPosition(int column, int row)
        {
            if (!this.BoundCheck(column, row))
            {
                throw new ArgumentException("out of tables bounds");
            }

            float x = 0;
            for (int c = 0; c < column; c++)
            {
                x += this.columnsWidth[c];
            }

            float y = 0;
            for (int r = 0; r < row; r++)
            {
                y += this.rowsHeight[r];
            }

            return new Vector2(x, y);
        }

        private bool BoundCheck(int column, int row)
        {
            return column >= 0 && column < this.columnsWidth.Length
                && row >= 0 && row < this.rowsHeight.Length;
        }

        private void Initialize(int columnCount, params float[] columnsAndRowsLength)
        {
            if (columnCount > columnsAndRowsLength.Length + 1)
            {
                throw new ArgumentException("the sizes of all columns and at least one row mus be defined.");
            }

            SetState("Normal");

            float width = 0, height = 0;

            List<float> columnWidhts = new List<float>();
            List<float> rowHeights = new List<float>();

            // store width and height
            for (int i = 0; i < columnsAndRowsLength.Length; i++)
            {
                if (i < columnCount)
                {
                    columnWidhts.Add(columnsAndRowsLength[i]);
                    width += columnsAndRowsLength[i];
                }
                else
                {
                    rowHeights.Add(columnsAndRowsLength[i]);
                    height += columnsAndRowsLength[i];
                }
            }

            this.columnsWidth = columnWidhts.ToArray();
            this.rowsHeight = rowHeights.ToArray();
            this.Size = new Vector2(width, height);

            this.cells = new Cell[this.columnsWidth.Length, this.rowsHeight.Length];
            for (int c = 0; c < this.columnsWidth.Length; c++)
            {
                for (int r = 0; r < this.rowsHeight.Length; r++)
                {
                    this.cells[c, r] = new Cell();
                }
            }
        }

        private struct Cell
        {
            // TODO: add information about fitting of content and stuff
            internal Widget Content;
        }
    }
}
